starts tracing at the memory location specified by "address". addressS and
RETURN starts single-stepping at the memory location specified by "address".
addressL and RETURN lists 19 lines of disassemby starting at the memory
location specific by "address". You can even use the built-in mini assembler
if you want (type "asm" and RETURN).
Peering Into Memory:
The 19 "windows on memory" can be used by typing "mem" and RETURN on the
command line. This puts the cursor on the far right of the first line in the
RAM subdisplay area. Type the address you want to watch and press RETURN.
That will move you to the next line (so you can set the address for the second
memory location). If you want to see two bytes starting at that address,
press "P". To see three bytes, press "L". "Z" toggles between direct-page
and absolute addressing, ":" toggles between direct, 2-byte indirect, and
3-byte indirect addressing. Press "?" for more info.
This provides a nice way to look at variables in memory, dereference
pointers/handles, etc. When the contents of any "peered into" location
changes, the corresponding line on GSBug's screen will change also.
Cheap Trick #5:
(this one's actually not cheap, it's pretty danged useful!) While
single-stepping or tracing, you can see other "screens" by pressing various
keys (this accounts for the weird effects I alluded to earlier). Press "S" to
see the SHR screen (i.e.: your desktop application's desktop), "D" to see the
double hi-res screen, "T" to see the text screen, "8" to see 80-column
display, "4" to see 40-column display, "H" to see the Hi-Res screen, "L" for
the Lo-Res screen, and ESC to exit single-stepping. This lets you see your
application's screen instead of GSBug's screen (makes it a LOT easier to
debug your apps when you can see their screens...).
Study For The Test:
I told you earlier that there would be a test at the end of this tutorial, so
now's your chance to kick back and study a bit. So far, we've covered what
the various parts of GSBug's screen mean, how to disassemble pieces of memory
(using "L"), how to single-step and trace (at different speeds) through your
application, how to set, use, and clear breakpoints, how to display various
screens, and how to set up the RAM subdisplay area.
Don't Touch That Dial!:
The material covered so far gives you a decent foundation to draw upon as you
hunt bugs in your own software. We've only lightly touched on what GSBug can
really do (I'm not typing all 150 or so pages of the manual into this
"introduction" to GSBug). GSBug offers a lot of power and capabilities that
should be learned by all developers.
Before I wrap up this tutorial I want to cover the use of templates and
describe some of the new features in GSBug v.1.5b11 that aren't described in
the APDA documentation (because we just added the features and haven't
replaced APDA's master manual yet).
Templates By Jim:
GSBug provides an easy way for you to view portions of memory through
templates. This allows you to "see" the data structures in memory just
like they appear in the documentation (i.e.: see them divided into the
various fields). The GSBug.Templates file that you were supposed to
have placed in the SYSTEM/SYSTEM.SETUP folder of your boot disk contains
a complete set of templates for use with our interface files. One of the
Apple II Developer Technical Support Engineers put these templates together
(and came up with a pretty neat way to build in a "help system" - so tell
Jim "thanks" next time a template bails you out of a jam).
GSBug does NOT automatically load those templates unless you rename them (see the "GSBug.Specs" file for more information). You have to tell GSBug to load
them (and you can unload them later). To load these templates, just type
"loadtemp */system/system.setup/gsbug.templates" and press RETURN. Keep
trying until you get it right - it does work (watch out for typos, etc).
To view a piece of memory with a template, simply determine the starting
address of the template. The starting address can be found in a number of
ways - you can dereference a pointer that you just pushed on the stack, etc.
Then, type an underscore, the type of structure you want used, a blank space,
and the starting address (don't forget the bank). (i.e.: if you know you
have a graf port starting at location 06/15E4, then type: "_grafport 06/15E4"
and press RETURN.
To use the built-in template help system that Jim came up with (thanks Jim!),
just type: "_template 0" and press return. This will give you a list of all
the categories of help you can get more info on (such as ADB, FONTS, etc).
The categories are grouped by toolbox manager. To get details on a particular
toolbox manager's tool calls, type "_toolmgrname 0" and press RETURN
(replace "_toolmgrname" with the name of any tool manager - lead with an
underscore or it won't work). (i.e.: "_quickdraw 0" for details on QuickDraw
data structures) For more details, read the separate documentation file on
using the templates.
If you want to create your own custom templates, then read the GSBug manual
(pages 86-88) or decipher the templates in the GSBug.Templates file. To
unload the templates (and free up the memory they're eating), type "killtemp"
and press RETURN from GSBug's command line.
The New Stuff:
As if all of this weren't reason enough to use GSBug, the man behind this
jewel added several more reasons (he calls them features). All of these are
fake tool calls that the debugger sees, intercepts, and acts on.
The new calls are SetMileStone, DebugStr, DebugVersion, and DebugStatus.
The two most important ones (in my opinion) are "SetMileStone" and "DebugStr".
SetMileStone simply changes the debugger's copyright message to be a string of
your choice and lets your app keep running. If you're having a problem
figuring out where your code was last at before it jumped off into the weeds,
then sprinkle SetMileStone calls into your source code (with different strings
on each, of course). Then, when your app chokes and dies, you'll be presented
with the text from the last SetMileStone that was executed.
DebugStr works like SetMileStone (i.e.: changes the copyright string
to something with info about your application) except it dumps you immediately
into GSBug. This is a little more work than Cheap Trick #1, but you can line
up your source easier (since you'll have the debug string's message to guide
you).
DebugVersion and DebugStatus act just like normal version and status calls for
regular tool sets - they simply allow you to verify whether GSBug is running
and if so, what version of the debugger is running before you try to make any
debugger tool calls.
The tool numbers and parameter lists for these calls are:
DebugStatus $06FF (non-zero = true, ToolLocator error it not loaded)
DebugStr $09FF pointer to Pascal-style string
DebugVersion $04FF ($159F for v.1.5B9)
SetMileStone $0AFF pointer to Pascal-style string
Cheap (and short) Trick #6:
If you get really fancy, you can build the strings for DebugStr and
SetMileStone on the fly and imbed the values of key variables into them to
further simplify locating bugs.
Calling all Debuggers:
Do _NOT_ leave calls to these debugger tools in your software when you ship it
to customers! Why? Because making these calls on a system that doesn't have
GSBug installed makes a real mess...
Want More Info?
Contact APDA and order the full package (you have a newer version of GSBug
with this file, but APDA has the full manual). Order it by calling APDA
(1-800-282-2732) and asking for part #A0037LL/A (the price is $30). Due to recent changes in APDA, you no longer need to be a member before you can order this product.